

Stack_Size      EQU     0x00000500  				;定义堆栈大小为1024byte
				AREA    STACK, NOINIT, READWRITE, ALIGN=3  ;定义一个数据段,标记为STACK，即栈，不写入初始值初，对RAM来说，即初始化为0，8字节对齐
Stack_Mem		SPACE	Stack_Size    				;保留Stack_Size大小的栈空间
__initial_sp  										;标号，代表堆栈顶部地址，后面有用

                PRESERVE8							;指示编译器8字节对齐
                THUMB								;指示编译器以后的指令为THUMB指令								


; Vector Table Mapped to Address 0 at Reset
				AREA    RESET, CODE, READONLY		;定义只读数据段，标记为RESET，其实放在CODE区，位于0地址
				EXPORT  __Vectors					;在程序中声明一个全局的标号__Vectors，该标号可在其他的文件中引用
				IMPORT 	NMI_Handler                ; NMI Handler
				IMPORT 	HardFault_Handler          ; Hard Fault Handler
				IMPORT 	MemManage_Handler          ; MPU Fault Handler
				IMPORT 	BusFault_Handler           ; Bus Fault Handler
				IMPORT 	UsageFault_Handler         ; Usage Fault Handler
				IMPORT 	SVC_Handler                ; SVCall Handler
				IMPORT 	DebugMon_Handler           ; Debug Monitor Handler
				IMPORT 	PendSV_Handler             ; PendSV Handler
				IMPORT 	SysTick_Handler            ; SysTick Handler	
					
__Vectors       DCD     __initial_sp				;当前地址写入一个字(32bit)数据，值应该为栈顶地址
                DCD     Reset_Handler              	;当前地址写入一个字(32bit)数据，值为Reset_Handler指向的地址值，即程序入口地址
				DCD     NMI_Handler                ; NMI Handler
                DCD     HardFault_Handler          ; Hard Fault Handler
                DCD     MemManage_Handler          ; MPU Fault Handler
                DCD     BusFault_Handler           ; Bus Fault Handler
                DCD     UsageFault_Handler         ; Usage Fault Handler
                DCD     0                          ; Reserved
                DCD     0                          ; Reserved
                DCD     0                          ; Reserved
                DCD     0                          ; Reserved
                DCD     SVC_Handler                ; SVCall Handler
                DCD     DebugMon_Handler           ; Debug Monitor Handler
                DCD     0                          ; Reserved
                DCD     PendSV_Handler             ; PendSV Handler
                DCD     SysTick_Handler            ; SysTick Handler

				AREA    |.text|, CODE, READONLY		;定义代码段，标记为.text

; Reset handler	;利用PROC、ENDP这一对伪指令把程序段分为若干个过程，使程序的结构加清晰
Reset_Handler   PROC								;过程的开始 
				EXPORT  Reset_Handler	[WEAK]		;[WEAK] 弱定义，意思是如果在别处也定义该标号(函数)，在链接时用别处的地址。
					
				IMPORT |Image$$RW_IRAM1$$Base|		;从别处导入data段的链接地址
				IMPORT |Image$$RW_IRAM1$$Length|	;从别处导入data段的长度
				IMPORT |Load$$RW_IRAM1$$Base|		;从别处导入data段的加载地址
				IMPORT |Image$$RW_IRAM1$$ZI$$Base|	;从别处导入ZI段的链接地址
				IMPORT |Image$$RW_IRAM1$$ZI$$Length|;从别处导入ZI段的长度

; 复制数据段
				LDR R0, = |Load$$RW_IRAM1$$Base|   	;将data段的加载地址存入R0寄存器
				LDR R1, = |Image$$RW_IRAM1$$Base|   ;将data段的链接地址存入R1寄存器
				LDR R2, = |Image$$RW_IRAM1$$Length| ;将data段的长度存入R2寄存器
CopyData		
				SUB R2, R2, #4						;每次复制4个字节的data段数据
				LDR R3, [R0, R2]					;把加载地址处的值取出到R3寄存器
				STR R3, [R1, R2]					;把取出的值从R3寄存器存入到链接地址					
				CMP R2, #0							;将计数和0相比较
				BNE CopyData						;如果不相等，跳转到CopyData标签处，相等则往下执行

; 清除BSS段
				LDR R0, = |Image$$RW_IRAM1$$ZI$$Base|   ;将bss段的链接地址存入R1寄存器
				LDR R1, = |Image$$RW_IRAM1$$ZI$$Length| ;将bss段的长度存入R2寄存器
CleanBss	
				SUB R1, R1, #4						;每次清除4个字节的bss段数据
				MOV R3, #0							;将0存入r3寄存器
				STR R3, [R0, R1]					;把R3寄存器存入到链接地址					
				CMP R1, #0							;将计数和0相比较
				BNE CleanBss						;如果不相等，跳转到CleanBss标签处，相等则往下执行
				
				
				IMPORT  mymain						;通知编译器要使用的标号在其他文件
				IMPORT	uart_init
				IMPORT	exception_init 
				
				BL		exception_init
				BL		uart_init 					;跳转去执行uart_init函数
				
				DCD		0XFFFFFFFF					;一个未定义的指令
				
				BL		mymain 						;跳转去执行main函数
				B		.							;原地跳转，即处于循环状态
				ENDP

                ALIGN 								;填充字节使地址对齐
                END									;整个汇编文件结束

